﻿#region zh-CHS 2006 - 2010 DemoSoft 团队 | en 2006-2010 DemoSoft Team

//     NOTES
// ---------------
//
// This file is a part of the MMOSE(Massively Multiplayer Online Server Engine) for .NET.
//
//                              2006-2010 DemoSoft Team
//
//
// First Version : by H.Q.Cai - mailto:caihuanqing@hotmail.com

/***************************************************************************
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published
 *   by the Free Software Foundation; either version 2.1 of the License, or
 *   (at your option) any later version.
 *
 ***************************************************************************/

#region zh-CHS 包含名字空间 | en Include namespace
using System;
using System.Diagnostics;
using System.Threading;
using Demo.Mmose.Core.Common;
using Demo.Mmose.Core.Common.SafeCollections;
using Demo.Mmose.Core.Util;
using Demo.Mmose.Core.Entity.Creature;
using System.Collections.Generic;
using Demo.Mmose.Core.Common.Template;
#endregion

namespace Demo.Mmose.Core.Entity.Item
{
    /// <summary>
    /// 道具容器
    /// </summary>
    /// <typeparam name="ItemT"></typeparam>
    public class ItemContainer<ItemT>
        where ItemT : ItemBase
    {
        #region zh-CHS 构造和初始化和清理 | en Constructors and Initializers and Dispose
        /// <summary>
        /// 
        /// </summary>
        public ItemContainer()
        {
        }

        /// <summary>
        /// 
        /// </summary>
        public ItemContainer( long lMinSlot, long lMaxSlot )
        {
            InitContainerSlot( lMinSlot, lMaxSlot );
        }

        /// <summary>
        /// 
        /// </summary>
        public void InitContainerSlot( long lMinSlot, long lMaxSlot )
        {
            if ( lMinSlot < 0 )
                throw new ArgumentOutOfRangeException( "lMinSlot", "BaseItemContainer<T>.InitContainerSlot(...) - m_MinSlot < 0 error!" );

            if ( lMaxSlot < 0 )
                throw new ArgumentOutOfRangeException( "lMaxSlot", "BaseItemContainer<T>.InitContainerSlot(...) - lMaxSlot < 0 error!" );

            if ( lMinSlot > lMaxSlot )
                throw new ArgumentException( "lMinSlot & lMaxSlot", "BaseItemContainer<T>.InitContainerSlot(...) - lMinSlot > lMaxSlot error!" );

            // 清空 初始化
            this.Clear();

            m_MinSlot = lMinSlot;
            m_MaxSlot = lMaxSlot;
        }
        #endregion

        #region zh-CHS 共有属性 | en Public Properties

        #region zh-CHS Serial属性 | en Public Properties

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private Serial m_Serial = new Serial();
        #endregion
        /// <summary>
        /// 道具的唯一序列号GUID
        /// </summary>
        public Serial Serial
        {
            get { return m_Serial; }
            set { m_Serial = value; }
        }

        #endregion

        #region zh-CHS MinSlot属性 | en Public Properties
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private long m_MinSlot = 0;
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public long MinSlot
        {
            get { return m_MinSlot; }
            protected set
            {
                if ( value < 0 )
                    throw new ArgumentOutOfRangeException( "value", "BaseItemContainer<T>.MinSlot - value < 0 error!" );

                if ( value > m_MaxSlot )
                    throw new ArgumentException( "value", "BaseItemContainer<T>.MinSlot - value > m_MaxSlot error!" );

                m_MinSlot = value;
            }
        }
        #endregion

        #region zh-CHS MaxSlot属性 | en Public Properties
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private long m_MaxSlot = long.MaxValue;
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public long MaxSlot
        {
            get { return m_MaxSlot; }
            protected set
            {
                if ( value < 0 )
                    throw new ArgumentOutOfRangeException( "value", "BaseItemContainer<T>.MaxSlot - value < 0 error!" );

                if ( value < m_MinSlot )
                    throw new ArgumentException( "value", "BaseItemContainer<T>.MaxSlot - value < m_MinSlot error!" );

                m_MaxSlot = value;
            }
        }
        #endregion

        #region zh-CHS IsContainerFull属性 | en Public Properties
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public bool IsContainerFull
        {
            get
            {
                if ( m_ToteSubItems.Count < ( ( this.MaxSlot - this.MinSlot ) + 1 ) )
                    return false;
                else
                    return true;
            }
        }
        #endregion

        #region zh-CHS FreeCount属性 | en Public Properties
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public int FreeCount
        {
            get
            {
                return ( ( (int)this.MaxSlot - (int)this.MinSlot ) + 1 ) - m_ToteSubItems.Count;
            }
        }
        #endregion

        #region zh-CHS BagSlotId属性 | en Public Properties

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private Serial m_BagSlotId = ItemContainer.SlotNotSet;
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public long BagSlotId
        {
            get { return m_BagSlotId; }
            internal set { m_BagSlotId = value; }
        }

        #endregion

        #region zh-CHS Count属性 | en Public Properties

        /// <summary>
        /// 
        /// </summary>
        public int Count
        {
            get { return m_ToteSubItems.Count; }
        }

        #endregion

        #region zh-CHS 道具列表 属性 | en Public Properties

        #region zh-CHS 私有常量 | en Private Constants
        /// <summary>
        /// 
        /// </summary>
        private readonly static ItemT[] s_ZeroValueArray = new ItemT[0];
        #endregion

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 人物的道具列表
        /// </summary>
        internal Dictionary<long, ItemT> m_ToteSubItems = new Dictionary<long, ItemT>( 32 );
        /// <summary>
        /// 
        /// </summary>
        internal ReaderWriterLockSlim m_LockToteSubItems = new ReaderWriterLockSlim();
        /// <summary>
        /// 
        /// </summary>
        private volatile ItemT[] m_ValueArray = s_ZeroValueArray;
        /// <summary>
        /// 
        /// </summary>
        private volatile bool m_bIsValueChange = true;
        #endregion

        #region zh-CHS 私有方法 | en Private Methods
        /// <summary>
        /// 
        /// </summary>
        private void InternalToCached()
        {
            if ( m_bIsValueChange == false )
                return;

            m_LockToteSubItems.EnterReadLock();
            try
            {
                if ( m_bIsValueChange == true )
                {
                    m_ValueArray = new ItemT[m_ToteSubItems.Count];

                    int iIndex = 0;
                    foreach ( KeyValuePair<long, ItemT> keyValuePair in m_ToteSubItems )
                    {
                        m_ValueArray[iIndex] = keyValuePair.Value;
                        ++iIndex;
                    }

                    // 最后设置
                    m_bIsValueChange = false;
                }
            }
            finally
            {
                m_LockToteSubItems.ExitReadLock();
            }
        }
        #endregion

        /// <summary>
        /// 人物的道具列表(包裹与身上)
        /// </summary>
        /// <returns></returns>
        [MultiThreadedWarning( "zh-CHS", "(道具)当前的数组是列表临时产生的,不能保存数组用于以后操作:警告!" )]
        public ItemT[] ToArray()
        {
            InternalToCached();

            return m_ValueArray;
        }

        #region zh-CHS 共有方法 | en Public Methods
        /// <summary>
        /// 添加道具
        /// </summary>
        /// <param name="item"></param>
        public bool AddSubItem( long lItemSlot, ItemT itemT )
        {
            if ( itemT == null )
                throw new ArgumentNullException( "itemT", "BaseItemContainer<T>.AddSubItem(...) - itemT == null error!" );

            if ( lItemSlot == ItemBase.SlotNotSet )
                return false;

            if ( lItemSlot > this.MaxSlot || lItemSlot < this.MinSlot )
                return false;
            
            EventHandler<AddingSubItemCallEventArgs<ItemT>> tempBeforeEventArgs = m_EventAddingSubItem;
            if ( tempBeforeEventArgs != null )
            {
                AddingSubItemCallEventArgs<ItemT> eventArgs = new AddingSubItemCallEventArgs<ItemT>( itemT, this );
                tempBeforeEventArgs( this, eventArgs );

                if ( eventArgs.IsCancel == true )
                    return false;
            }

            bool tryAdd = false;

            m_LockToteSubItems.EnterWriteLock();
            try
            {
                if ( m_ToteSubItems.ContainsKey( lItemSlot ) == false )
                {
                    m_ToteSubItems.Add( lItemSlot, itemT );
                    itemT.SlotId = lItemSlot;

                    m_bIsValueChange = tryAdd = true;
                }
            }
            finally
            {
                m_LockToteSubItems.ExitWriteLock();
            }

            if ( tryAdd == false )
                return false;

            EventHandler<AddedSubItemCallEventArgs<ItemT>> tempAfterEventArgs = m_EventAddedSubItem;
            if ( tempAfterEventArgs != null )
            {
                AddedSubItemCallEventArgs<ItemT> eventArgs = new AddedSubItemCallEventArgs<ItemT>( itemT, this );
                tempAfterEventArgs( this, eventArgs );
            }

            return true;
        }

        /// <summary>
        /// 移出道具
        /// </summary>
        /// <param name="item"></param>
        public bool RemoveSubItem( long lItemSlot )
        {
            if ( lItemSlot > this.MaxSlot || lItemSlot < this.MinSlot )
                return false;

            ItemT itemT = FindSubItemOnSlot( lItemSlot );
            if ( itemT == null )
                return false;

            EventHandler<RemovingSubItemCallEventArgs<ItemT>> tempBeforeEventArgs = m_EventRemovingSubItem;
            if ( tempBeforeEventArgs != null )
            {
                RemovingSubItemCallEventArgs<ItemT> eventArgs = new RemovingSubItemCallEventArgs<ItemT>( itemT, this );
                tempBeforeEventArgs( this, eventArgs );

                if ( eventArgs.IsCancel == true )
                    return false;
            }

            bool isRemove = false;

            m_LockToteSubItems.EnterWriteLock();
            try
            {
                if ( m_ToteSubItems.Remove( lItemSlot ) == true )
                    m_bIsValueChange = isRemove = true;

                itemT.SlotId = ItemBase.SlotNotSet;
            }
            finally
            {
                m_LockToteSubItems.ExitWriteLock();
            }

            if ( isRemove == false )
                return false;

            EventHandler<RemovedSubItemCallEventArgs<ItemT>> tempAfterEventArgs = m_EventRemovedSubItem;
            if ( tempAfterEventArgs != null )
            {
                RemovedSubItemCallEventArgs<ItemT> eventArgs = new RemovedSubItemCallEventArgs<ItemT>( itemT, this );
                tempAfterEventArgs( this, eventArgs );
            }

            return true;
        }

        /// <summary>
        /// 交换道具
        /// </summary>
        /// <param name="lItemSlot"></param>
        /// <param name="lItemSlot"></param>
        /// <returns></returns>
        public bool SwapSubItem( long srcItemSlot, long dstItemSlot )
        {
            if ( srcItemSlot > this.MaxSlot || srcItemSlot < this.MinSlot )
                return false;

            if ( dstItemSlot > this.MaxSlot || dstItemSlot < this.MinSlot )
                return false;

            ItemT srcSubItem = FindSubItemOnSlot( srcItemSlot );
            ItemT dstSubItem = FindSubItemOnSlot( dstItemSlot );

            EventHandler<SwapingSubItemCallEventArgs<ItemT>> tempBeforeEventArgs = m_EventSwapingSubItem;
            if ( tempBeforeEventArgs != null )
            {
                SwapingSubItemCallEventArgs<ItemT> eventArgs = new SwapingSubItemCallEventArgs<ItemT>( srcItemSlot, srcSubItem, dstItemSlot, dstSubItem, this );
                tempBeforeEventArgs( this, eventArgs );

                if ( eventArgs.IsCancel == true )
                    return false;
            }

            bool isSwap = false;

            m_LockToteSubItems.EnterWriteLock();
            try
            {
                do
                {
                    bool srcIsNone = false;
                    ItemT srcValue = default( ItemT );
                    if ( m_ToteSubItems.TryGetValue( srcItemSlot, out srcValue ) == false )
                        break;

                    bool dstIsNone = false;
                    ItemT dstValue = default( ItemT );
                    if ( m_ToteSubItems.TryGetValue( dstItemSlot, out dstValue ) == false )
                        dstIsNone = true;

                    if ( srcIsNone == false )       // 来源数据存在，添加数据
                    {
                        m_ToteSubItems[dstItemSlot] = srcValue;
                        srcValue.SlotId = dstItemSlot;
                    }
                    else                            // 来源数据不存在，删除目标数据
                    {
                        if ( dstIsNone == false )   // 如果目标数据存在，删除目标数据（因为来源数据不存在）
                            m_ToteSubItems.Remove( dstItemSlot );
                    }

                    if ( dstIsNone == false )       // 目标数据存在，添加数据
                    {
                        m_ToteSubItems[srcItemSlot] = dstValue;
                        dstValue.SlotId = srcItemSlot;
                    }
                    else                            // 目标数据不存在，删除来源数据
                    {
                        if ( srcIsNone == false )   // 如果来源数据存在，删除来源数据（因为目标数据不存在）
                            m_ToteSubItems.Remove( srcItemSlot );
                    }

                    m_bIsValueChange = isSwap = true;
                } while ( false );
            }
            finally
            {
                m_LockToteSubItems.ExitWriteLock();
            }

            if ( isSwap == false )
                return false;

            EventHandler<SwapedSubItemCallEventArgs<ItemT>> tempAfterEventArgs = m_EventSwapedSubItem;
            if ( tempAfterEventArgs != null )
            {
                SwapedSubItemCallEventArgs<ItemT> eventArgs = new SwapedSubItemCallEventArgs<ItemT>( srcItemSlot, srcSubItem, dstItemSlot, dstSubItem, this );
                tempAfterEventArgs( this, eventArgs );
            }

            return true;
        }

        /// <summary>
        /// 找道具
        /// </summary>
        /// <param name="layer"></param>
        /// <returns></returns>
        public ItemT FindSubItemOnSlot( long lItemSlot )
        {
            ItemT resultItem = default( ItemT );

            m_LockToteSubItems.EnterReadLock();
            try
            {
                m_ToteSubItems.TryGetValue( lItemSlot, out resultItem );
            }
            finally
            {
                m_LockToteSubItems.ExitReadLock();
            }

            return resultItem;
        }

        /// <summary>
        /// 
        /// </summary>
        public void Clear()
        {
            ItemT[] valueArray = null;

            m_LockToteSubItems.EnterWriteLock();
            try
            {
                if ( m_bIsValueChange == true )
                {
                    m_ValueArray = new ItemT[m_ToteSubItems.Count];

                    int iIndex = 0;
                    foreach ( KeyValuePair<long, ItemT> keyValuePair in m_ToteSubItems )
                    {
                        m_ValueArray[iIndex] = keyValuePair.Value;
                        keyValuePair.Value.SlotId = ItemBase.SlotNotSet;

                        ++iIndex;
                    }
                }

                valueArray = m_ValueArray;

                // 清空
                m_ToteSubItems.Clear();
                m_ValueArray = s_ZeroValueArray;

                // 最后设置
                m_bIsValueChange = false;
            }
            finally
            {
                m_LockToteSubItems.ExitWriteLock();
            }

            if ( valueArray == null )
                return;

            foreach ( var item in valueArray )
            {
                EventHandler<RemovedSubItemCallEventArgs<ItemT>> tempAfterEventArgs = m_EventRemovedSubItem;
                if ( tempAfterEventArgs != null )
                {
                    RemovedSubItemCallEventArgs<ItemT> eventArgs = new RemovedSubItemCallEventArgs<ItemT>( item, this );
                    tempAfterEventArgs( this, eventArgs );
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="item"></param>
        public bool AddToFreeSlot( ItemT itemT )
        {
            long iItemSlotResult = ItemBase.SlotNotSet;

            if ( this.IsContainerFull == true )
                return false;

            bool tryAdd = false;
            m_LockToteSubItems.EnterWriteLock();
            try
            {

                for ( long iIndexSlot = this.MinSlot; iIndexSlot <= this.MaxSlot; iIndexSlot++ )
                {
                    if ( m_ToteSubItems.ContainsKey( iIndexSlot ) == true )
                        continue;
                    else
                    {
                        m_ToteSubItems.Add( iIndexSlot, itemT );
                        itemT.SlotId = iIndexSlot;

                        m_bIsValueChange = tryAdd = true;

                        break;
                    }
                }
            }
            finally
            {
                m_LockToteSubItems.ExitWriteLock();
            }

            return tryAdd;
        }

        /// <summary>
        /// 
        /// </summary>
        public struct AddToFreeSlotResult
        {
            internal List<ItemT> m_Added;
            public IEnumerable<ItemT> Added
            {
                get { return m_Added; }
            }

            internal List<ItemT> m_NotAdded;
            public IEnumerable<ItemT> NotAdded
            {
                get { return m_NotAdded; }
            }

            internal int m_AddedCount;
            public int AddedCount
            {
                get { return m_AddedCount; }
            }

            internal int m_NotAddedCount;
            public int NotAddedCount
            {
                get { return m_NotAddedCount; }
            }

            internal bool m_IsSucceeded;
            public bool IsSucceeded
            {
                get { return m_IsSucceeded; }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="item"></param>
        public AddToFreeSlotResult AddToFreeSlot( ICollection<ItemT> items, bool allSucceeded )
        {
            AddToFreeSlotResult result = new AddToFreeSlotResult { m_Added = new List<ItemT>( items.Count ), m_NotAdded = new List<ItemT>( items.Count ), m_AddedCount = 0, m_NotAddedCount = 0, m_IsSucceeded = false };

            if ( allSucceeded == false ) // 局部添加
            {
                foreach ( var item in items )
                {
                    EventHandler<AddingSubItemCallEventArgs<ItemT>> tempBeforeEventArgs = m_EventAddingSubItem;
                    if ( tempBeforeEventArgs != null )
                    {
                        AddingSubItemCallEventArgs<ItemT> eventArgs = new AddingSubItemCallEventArgs<ItemT>( item, this );
                        tempBeforeEventArgs( this, eventArgs );

                        if ( eventArgs.IsCancel == true )
                        {
                            result.m_NotAddedCount++;
                            result.m_NotAdded.Add( item );

                            continue;
                        }
                    }

                    if ( this.AddToFreeSlot( item ) == false )
                    {
                        result.m_NotAddedCount++;
                        result.m_NotAdded.Add( item );

                        continue;
                    }
                    else
                    {
                        result.m_AddedCount++;
                        result.m_Added.Add( item );
                    }

                    EventHandler<AddedSubItemCallEventArgs<ItemT>> tempAfterEventArgs = m_EventAddedSubItem;
                    if ( tempAfterEventArgs != null )
                    {
                        AddedSubItemCallEventArgs<ItemT> eventArgs = new AddedSubItemCallEventArgs<ItemT>( item, this );
                        tempAfterEventArgs( this, eventArgs );
                    }
                }

                result.m_IsSucceeded = true;
            }
            else // 全部添加
            {
                if ( this.FreeCount < items.Count )
                    return result;

                foreach ( var item in items )
                {
                    EventHandler<AddingSubItemCallEventArgs<ItemT>> tempBeforeEventArgs = m_EventAddingSubItem;
                    if ( tempBeforeEventArgs != null )
                    {
                        AddingSubItemCallEventArgs<ItemT> eventArgs = new AddingSubItemCallEventArgs<ItemT>( item, this );
                        tempBeforeEventArgs( this, eventArgs );

                        if ( eventArgs.IsCancel == true )
                            return result;
                    }
                }

                m_LockToteSubItems.EnterWriteLock();
                try
                {
                    do
                    {
                        if ( this.FreeCount < items.Count )
                            break;

                        long iIndexSlot = this.MinSlot;

                        foreach ( var item in items )
                        {
                            for ( ; iIndexSlot <= this.MaxSlot; iIndexSlot++ )
                            {
                                if ( m_ToteSubItems.ContainsKey( iIndexSlot ) == true )
                                    continue;

                                m_ToteSubItems.Add( iIndexSlot, item );
                                item.SlotId = iIndexSlot;

                                result.m_AddedCount++;
                                result.m_Added.Add( item );

                                break; // 添加完成
                            }

                            EventHandler<AddedSubItemCallEventArgs<ItemT>> tempAfterEventArgs = m_EventAddedSubItem;
                            if ( tempAfterEventArgs != null )
                            {
                                AddedSubItemCallEventArgs<ItemT> eventArgs = new AddedSubItemCallEventArgs<ItemT>( item, this );
                                tempAfterEventArgs( this, eventArgs );
                            }
                        }

                        m_bIsValueChange = result.m_IsSucceeded = true;

                    } while ( false );
                }
                finally
                {
                    m_LockToteSubItems.ExitWriteLock();
                }
            }

            return result;
        }
        
        /// <summary>
        /// 
        /// </summary>
        /// <param name="layer"></param>
        /// <returns></returns>
        public bool TryFindFreeSlot( ref long iItemSlotResult )
        {
            if ( this.IsContainerFull == true )
                return false;

            bool isFind = false;

            m_LockToteSubItems.EnterReadLock();
            try
            {
                for ( long iIndexSlot = this.MinSlot; iIndexSlot <= this.MaxSlot; iIndexSlot++ )
                {
                    if ( m_ToteSubItems.ContainsKey( iIndexSlot ) == true )
                        continue;
                    else
                    {
                        isFind = true;
                        iItemSlotResult = iIndexSlot;

                        break;
                    }
                }
            }
            finally
            {
                m_LockToteSubItems.ExitReadLock();
            }

            return isFind;
        }

        #endregion

        #endregion

        #region zh-CHS ItemContainerState属性 | en Public Properties

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 道具的的状态
        /// </summary>
        private ItemContainerState<ItemT> m_ItemContainerState = null;
        #endregion
        /// <summary>
        /// 道具的的状态
        /// </summary>
        public ItemContainerState<ItemT> ItemContainerState
        {
            get { return m_ItemContainerState; }
            protected set { m_ItemContainerState = value; }
        }

        #endregion

        #endregion

        #region zh-CHS 共有事件 | en Public Event

        #region zh-CHS AddingSubItem事件 | en Public Event
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        internal EventHandler<AddingSubItemCallEventArgs<ItemT>> m_EventAddingSubItem;
        /// <summary>
        /// 
        /// </summary>
        private SpinLock m_LockEventAddingSubItem = new SpinLock();
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public event EventHandler<AddingSubItemCallEventArgs<ItemT>> AddingSubItem
        {
            add
            {
                SpinLockEx.ReliableEnter( ref m_LockEventAddingSubItem );
                try
                {
                    m_EventAddingSubItem += value;
                }
                finally
                {
                    m_LockEventAddingSubItem.Exit();
                }
            }
            remove
            {
                SpinLockEx.ReliableEnter( ref m_LockEventAddingSubItem );
                try
                {
                    m_EventAddingSubItem -= value;
                }
                finally
                {
                    m_LockEventAddingSubItem.Exit();
                }
            }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        internal EventHandler<AddedSubItemCallEventArgs<ItemT>> m_EventAddedSubItem;
        /// <summary>
        /// 
        /// </summary>
        private SpinLock m_LockEventAddedSubItem = new SpinLock();
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public event EventHandler<AddedSubItemCallEventArgs<ItemT>> AddedSubItem
        {
            add
            {
                SpinLockEx.ReliableEnter( ref m_LockEventAddedSubItem );
                try
                {
                    m_EventAddedSubItem += value;
                }
                finally
                {
                    m_LockEventAddedSubItem.Exit();
                }
            }
            remove
            {
                SpinLockEx.ReliableEnter( ref m_LockEventAddedSubItem );
                try
                {
                    m_EventAddedSubItem -= value;
                }
                finally
                {
                    m_LockEventAddedSubItem.Exit();
                }
            }
        }
        #endregion

        #region zh-CHS RemovingSubItem事件 | en Public Event
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        internal EventHandler<RemovingSubItemCallEventArgs<ItemT>> m_EventRemovingSubItem;
        /// <summary>
        /// 
        /// </summary>
        private SpinLock m_LockEventRemovingSubItem = new SpinLock();
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public event EventHandler<RemovingSubItemCallEventArgs<ItemT>> RemovingSubItem
        {
            add
            {
                SpinLockEx.ReliableEnter( ref m_LockEventRemovingSubItem );
                try
                {
                    m_EventRemovingSubItem += value;
                }
                finally
                {
                    m_LockEventRemovingSubItem.Exit();
                }
            }
            remove
            {
                SpinLockEx.ReliableEnter( ref m_LockEventRemovingSubItem );
                try
                {
                    m_EventRemovingSubItem -= value;
                }
                finally
                {
                    m_LockEventRemovingSubItem.Exit();
                }
            }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        internal EventHandler<RemovedSubItemCallEventArgs<ItemT>> m_EventRemovedSubItem;
        /// <summary>
        /// 
        /// </summary>
        private SpinLock m_LockEventRemovedSubItem = new SpinLock();
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public event EventHandler<RemovedSubItemCallEventArgs<ItemT>> RemovedSubItem
        {
            add
            {
                SpinLockEx.ReliableEnter( ref m_LockEventRemovedSubItem );
                try
                {
                    m_EventRemovedSubItem += value;
                }
                finally
                {
                    m_LockEventRemovedSubItem.Exit();
                }
            }
            remove
            {
                SpinLockEx.ReliableEnter( ref m_LockEventRemovedSubItem );
                try
                {
                    m_EventRemovedSubItem -= value;
                }
                finally
                {
                    m_LockEventRemovedSubItem.Exit();
                }
            }
        }
        #endregion

        #region zh-CHS SwapingSubItem事件 | en Public Event
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        internal EventHandler<SwapingSubItemCallEventArgs<ItemT>> m_EventSwapingSubItem;
        /// <summary>
        /// 
        /// </summary>
        private SpinLock m_LockEventSwapingSubItem = new SpinLock();
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public event EventHandler<SwapingSubItemCallEventArgs<ItemT>> SwapingSubItem
        {
            add
            {
                SpinLockEx.ReliableEnter( ref m_LockEventSwapingSubItem );
                try
                {
                    m_EventSwapingSubItem += value;
                }
                finally
                {
                    m_LockEventSwapingSubItem.Exit();
                }
            }
            remove
            {
                SpinLockEx.ReliableEnter( ref m_LockEventSwapingSubItem );
                try
                {
                    m_EventSwapingSubItem -= value;
                }
                finally
                {
                    m_LockEventSwapingSubItem.Exit();
                }
            }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        internal EventHandler<SwapedSubItemCallEventArgs<ItemT>> m_EventSwapedSubItem;
        /// <summary>
        /// 
        /// </summary>
        private SpinLock m_LockEventSwapedSubItem = new SpinLock();
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public event EventHandler<SwapedSubItemCallEventArgs<ItemT>> SwapedSubItem
        {
            add
            {
                SpinLockEx.ReliableEnter( ref m_LockEventSwapedSubItem );
                try
                {
                    m_EventSwapedSubItem += value;
                }
                finally
                {
                    m_LockEventSwapedSubItem.Exit();
                }
            }
            remove
            {
                SpinLockEx.ReliableEnter( ref m_LockEventSwapedSubItem );
                try
                {
                    m_EventSwapedSubItem -= value;
                }
                finally
                {
                    m_LockEventSwapedSubItem.Exit();
                }
            }
        }
        #endregion

        #endregion

    }

    /// <summary>
    /// 道具容器
    /// </summary>
    public class ItemContainer<ItemT, ItemTemplateT> : ItemContainer<ItemT>, ISupportTemplate<ItemT>
        where ItemT : ItemBase<ItemTemplateT>
        where ItemTemplateT : ItemTemplateBase
    {

        #region zh-CHS 构造和初始化和清理 | en Constructors and Initializers and Dispose

        #region zh-CHS 私有的事件处理函数 | en Private Event Handlers
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ItemContainer_RemovedSubItem( object sender, RemovedSubItemCallEventArgs<ItemT> eventArgs )
        {
            m_SupportTemplate.RemoveTemplate( eventArgs.RemoveSubItem );
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ItemContainer_AddedSubItem( object sender, AddedSubItemCallEventArgs<ItemT> eventArgs )
        {
            m_SupportTemplate.AddTemplate( eventArgs.AddSubItem );
        }
        #endregion
        /// <summary>
        /// 
        /// </summary>
        public ItemContainer()
        {
            base.AddedSubItem += new EventHandler<AddedSubItemCallEventArgs<ItemT>>( ItemContainer_AddedSubItem );
            base.RemovedSubItem += new EventHandler<RemovedSubItemCallEventArgs<ItemT>>( ItemContainer_RemovedSubItem );
        }

        #endregion

        #region zh-CHS 共有方法 | en Public Methods

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 
        /// </summary>
        private SupportTemplate<ItemT> m_SupportTemplate = new SupportTemplate<ItemT>();
        #endregion
        /// <summary>
        /// 
        /// </summary>
        /// <param name="templateId"></param>
        /// <returns></returns>
        public IEnumerable<ItemT> FindTemplateOnId( long templateId )
        {
            return m_SupportTemplate.FindTemplateOnId( templateId );
        }

        #endregion

    }

    /// <summary>
    /// 道具容器
    /// </summary>
    public class ItemContainer : ItemContainer<ItemBase>
    {

        #region zh-CHS 共有常量 | en Public Constants
        /// <summary>
        /// 
        /// </summary>
        public static readonly long SlotNotSet = Serial.MinusOne;
        #endregion

    }
}
#endregion